from typing import Optional, List, Dict, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func

from app.models.tenant import Tenant
from app.services.base import BaseService


class TenantService(BaseService[Tenant]):
    """租户服务"""

    def __init__(self):
        super().__init__(Tenant)

    async def get_by_code(self, db: AsyncSession, *, code: str) -> Optional[Tenant]:
        """根据租户编码获取租户"""
        query = select(Tenant).where(
            Tenant.code == code,
            Tenant.is_deleted == False
        )
        result = await db.execute(query)
        return result.scalar_one_or_none()

    async def get_active_tenant(self, db: AsyncSession, *, tenant_id: int) -> Optional[Tenant]:
        """获取活跃租户"""
        query = select(Tenant).where(
            Tenant.id == tenant_id,
            Tenant.status == True,
            Tenant.is_deleted == False
        )
        result = await db.execute(query)
        return result.scalar_one_or_none()

    async def create_tenant(self, db: AsyncSession, *, obj_in: Dict[str, Any]) -> Tenant:
        """创建租户"""
        # 检查租户编码是否已存在
        existing_tenant = await self.get_by_code(db, code=obj_in["code"])
        if existing_tenant:
            raise ValueError("租户编码已存在")

        tenant = await self.create(db, obj_in=obj_in)
        return tenant

    async def update_tenant(
        self, db: AsyncSession, *, db_obj: Tenant, obj_in: Dict[str, Any]
    ) -> Tenant:
        """更新租户"""
        # 如果更新编码，检查是否已存在
        if "code" in obj_in and obj_in["code"] != db_obj.code:
            existing_tenant = await self.get_by_code(db, code=obj_in["code"])
            if existing_tenant:
                raise ValueError("租户编码已存在")

        tenant = await self.update(db, db_obj=db_obj, obj_in=obj_in)
        return tenant

    async def update_status(
        self, db: AsyncSession, *, tenant: Tenant, status: bool
    ) -> Tenant:
        """更新租户状态"""
        tenant.status = status
        db.add(tenant)
        await db.commit()
        await db.refresh(tenant)
        return tenant

    async def get_tenant_config(
        self, db: AsyncSession, *, tenant_id: int
    ) -> Optional[Dict[str, Any]]:
        """获取租户配置"""
        tenant = await self.get_by_id(db, id=tenant_id)
        if tenant:
            return tenant.config or {}
        return None

    async def update_tenant_config(
        self, db: AsyncSession, *, tenant_id: int, config: Dict[str, Any]
    ) -> Optional[Tenant]:
        """更新租户配置"""
        tenant = await self.get_by_id(db, id=tenant_id)
        if tenant:
            tenant.config = config
            db.add(tenant)
            await db.commit()
            await db.refresh(tenant)
        return tenant

    async def get_tenant_statistics(self, db: AsyncSession, *, tenant_id: int) -> Dict[str, Any]:
        """获取租户统计信息"""
        # 这里可以统计租户下的用户数量、部门数量等
        # 需要根据实际需求实现
        from app.models.user import User, Dept

        # 统计用户数量
        user_count_query = select(func.count(User.id)).where(
            User.tenant_id == str(tenant_id),
            User.is_deleted == False
        )
        user_count_result = await db.execute(user_count_query)
        user_count = user_count_result.scalar() or 0

        # 统计部门数量
        dept_count_query = select(func.count(Dept.id)).where(
            Dept.tenant_id == str(tenant_id),
            Dept.is_deleted == False
        )
        dept_count_result = await db.execute(dept_count_query)
        dept_count = dept_count_result.scalar() or 0

        return {
            "user_count": user_count,
            "dept_count": dept_count,
        }

    async def is_tenant_expired(self, db: AsyncSession, *, tenant_id: int) -> bool:
        """检查租户是否过期"""
        tenant = await self.get_by_id(db, id=tenant_id)
        if not tenant or not tenant.expire_time:
            return False

        from datetime import datetime
        try:
            expire_time = datetime.strptime(tenant.expire_time, "%Y-%m-%d %H:%M:%S")
            return datetime.now() > expire_time
        except (ValueError, TypeError):
            return False

    async def search_tenants(
        self,
        db: AsyncSession,
        *,
        keyword: str,
        skip: int = 0,
        limit: int = 20,
    ) -> List[Tenant]:
        """搜索租户"""
        from sqlalchemy import or_, and_

        query = select(Tenant).where(
            and_(
                Tenant.is_deleted == False,
                or_(
                    Tenant.name.like(f"%{keyword}%"),
                    Tenant.code.like(f"%{keyword}%"),
                    Tenant.contact_user.like(f"%{keyword}%"),
                )
            )
        ).offset(skip).limit(limit)

        result = await db.execute(query)
        return result.scalars().all()

    async def get_tenants_with_pagination(
        self,
        db: AsyncSession,
        *,
        page: int = 1,
        page_size: int = 10,
        filters: dict = None
    ) -> tuple:
        """分页获取租户列表"""
        from sqlalchemy import and_, or_

        # 构建查询条件
        conditions = [Tenant.is_deleted == False]

        if filters:
            if filters.get("keyword"):
                keyword = filters["keyword"]
                conditions.append(
                    or_(
                        Tenant.name.like(f"%{keyword}%"),
                        Tenant.code.like(f"%{keyword}%"),
                        Tenant.contact_user.like(f"%{keyword}%"),
                        Tenant.contact_email.like(f"%{keyword}%")
                    )
                )

            if filters.get("status") is not None:
                conditions.append(Tenant.status == filters["status"])

        # 计算总数
        count_query = select(func.count(Tenant.id)).where(and_(*conditions))
        count_result = await db.execute(count_query)
        total = count_result.scalar() or 0

        # 分页查询
        offset = (page - 1) * page_size
        query = select(Tenant).where(and_(*conditions)).offset(offset).limit(page_size).order_by(Tenant.created_at.desc())

        result = await db.execute(query)
        tenants = result.scalars().all()

        # 获取每个租户的统计信息
        tenant_list = []
        for tenant in tenants:
            tenant_dict = {
                "id": tenant.id,
                "name": tenant.name,
                "code": tenant.code,
                "contact_user": tenant.contact_user,
                "contact_phone": tenant.contact_phone,
                "contact_email": tenant.contact_email,
                "address": tenant.address,
                "description": tenant.description,
                "logo": tenant.logo,
                "domain": tenant.domain,
                "status": tenant.status,
                "expire_time": tenant.expire_time,
                "package_id": tenant.package_id,
                "config": tenant.config,
                "created_at": tenant.created_at.isoformat() if tenant.created_at else None,
                "updated_at": tenant.updated_at.isoformat() if tenant.updated_at else None,
            }

            # 获取用户统计
            stats = await self.get_tenant_statistics(db, tenant_id=tenant.id)
            tenant_dict["user_count"] = stats.get("user_count", 0)

            tenant_list.append(tenant_dict)

        return tenant_list, total


# 创建租户服务实例
tenant_service = TenantService()